package top.jfunc.common.compress;

import top.jfunc.common.utils.FileUtil;
import top.jfunc.common.utils.IoUtil;

import java.io.*;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;

/**
 * @author xiongshiyan at 2022/5/26 , contact me with email yanshixiong@126.com or phone 15208384257
 */
public class ZipFileCompressor implements FileCompressor{
    @Override
    public void compress(File src, File dest) throws CompressException {
        if(dest.isDirectory()){
            throw new CompressException("目标文件必须是一个文件");
        }

        try {
            FileUtil.makeSureExistFile(dest);
        } catch (IOException e) {
            throw new CompressException(e);
        }

        try (ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(dest))){
            zip(src,zos,"");
        }catch (Exception e){
            throw new CompressException(e);
        }


    }
    private void zip(File src, ZipOutputStream zos, String dir) throws IOException{
        String d = !"".equals(dir) ? (dir + File.separator + src.getName()) : src.getName();

        if (src.isDirectory()) {

            File[] files = src.listFiles();

            if(null == files){
                return;
            }

            for (File file:files){
                zip(file, zos, d);
            }


        } else {

            String entryName = null;

            if (!"".equals(dir)) {
                entryName = d;
            }else {
                entryName = src.getName();
            }
            ZipEntry entry = new ZipEntry(entryName);

            zos.putNextEntry(entry);

            try (InputStream is = new FileInputStream(src)) {
                IoUtil.copy(is,zos);
            }

        }
    }
    @Override
    public void unCompress(File src, File dest) throws CompressException {
        try {
            unzip(src,dest);
        } catch (Exception e) {
            throw new CompressException(e);
        }

    }

    private void unzip(File zipFile,File dest) throws IOException{
        if(dest.isFile()){
            throw new IOException("目标文件必须是一个目录");
        }

        FileUtil.makeSureExistDir(dest);

        ZipFile zip = new ZipFile(zipFile);

        for(Enumeration entries = zip.entries(); entries.hasMoreElements();) {

            ZipEntry entry = (ZipEntry) entries.nextElement();

            String zipEntryName = entry.getName();

            String absolutePath = dest.getAbsolutePath();
            if(!absolutePath.endsWith(File.separator)){
                absolutePath=absolutePath+File.separator;
            }
            String outPath = (absolutePath + zipEntryName).replaceAll("\\*", "/");

            //判断路径是否存在,不存在则创建文件路径

            File file = new File(outPath.substring(0, outPath.lastIndexOf(File.separator)));

            if (!file.exists()) {

                file.mkdirs();

            }

            //判断文件全路径是否为文件夹,如果是上面已经上传,不需要解压

            if (new File(outPath).isDirectory()) {
                continue;
            }

            //输出文件路径信息

            try (InputStream in = zip.getInputStream(entry);
                 OutputStream out = new FileOutputStream(outPath)) {
                IoUtil.copy(in, out);
            }

        }

    }


    @Override
    public String toString(){
        return getClass().getName();
    }
}
